/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 */

package org.apache.solr.update;

import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.index.Term;
import org.apache.lucene.document.Document;
import org.apache.lucene.search.Query;

import java.util.HashSet;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;
import java.io.IOException;
import java.net.URL;

import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.search.QueryParsing;
import org.apache.solr.update.UpdateHandler;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.SolrCore;
import org.apache.solr.handler.NonUpdateHandler;

/**
 * <code>DirectUpdateHandler</code> implements an UpdateHandler where documents are added
 * directly to the main lucene index as opposed to adding to a separate smaller index.
 * For this reason, not all combinations to/from pending and committed are supported.
 *
 * @version $Id: DirectUpdateHandler.java 1065312 2011-01-30 16:08:25Z rmuir $
 * @since solr 0.9
 *
 * @deprecated Use {@link DirectUpdateHandler2} instead.  This is only kept around for back-compatibility (way back).
 */
@Deprecated
public class DirectUpdateHandler extends NonUpdateHandler {
	  public DirectUpdateHandler(SolrCore core) throws IOException {
		    super(core);
	  }
//
//  // the set of ids in the "pending set" (those docs that have been added, but
//  // that are not yet visible.
//  final HashSet<String> pset;
//  IndexWriter writer;
//  SolrIndexSearcher searcher;
//  int numAdds=0;     // number of docs added to the pending set
//  int numPending=0;  // number of docs currently in this pending set
//  int numDeleted=0;  // number of docs deleted or
//
//
//  public DirectUpdateHandler(SolrCore core) throws IOException {
//    super(core);
//    pset = new HashSet<String>(256);
//  }
//
//
//  protected void openWriter() throws IOException {
//    if (writer==null) {
//      writer = createMainIndexWriter("DirectUpdateHandler", false);
//    }
//  }
//
//  protected void closeWriter() throws IOException {
//    try {
//      if (writer!=null) writer.close();
//    } finally {
//      // TODO: if an exception causes the writelock to not be
//      // released, we could delete it here.
//      writer=null;
//    }
//  }
//
//  protected void openSearcher() throws IOException {
//    if (searcher==null) {
//      searcher = core.newSearcherForUpdate("DirectUpdateHandler",UpdateHandler.UPDATEPARTION);
//    }
//  }
//
//  protected void closeSearcher() throws IOException {
//    try {
//      if (searcher!=null) searcher.close();
//    } finally {
//      // TODO: if an exception causes the writelock to not be
//      // released, we could delete it here.
//      searcher=null;
//    }
//  }
//
//  protected void doAdd(Document doc) throws IOException {
//    closeSearcher(); openWriter();
//    writer.addDocument(doc);
//  }
//
//  protected boolean existsInIndex(String indexedId) throws IOException {
//    if (idField == null) throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"Operation requires schema to have a unique key field");
//
//    closeWriter();
//    openSearcher();
//    IndexReader ir = searcher.getReader();
//    TermDocs tdocs = null;
//    boolean exists=false;
//    try {
//      tdocs = ir.termDocs(idTerm(indexedId));
//      if (tdocs.next()) exists=true;
//    } finally {
//      try { if (tdocs != null) tdocs.close(); } catch (Exception e) {}
//    }
//    return exists;
//  }
//
//
//  protected int deleteInIndex(String indexedId) throws IOException {
//    if (idField == null) throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"Operation requires schema to have a unique key field");
//
//    closeWriter(); openSearcher();
//    IndexReader ir = searcher.getReader();
//    TermDocs tdocs = null;
//    int num=0;
//    try {
//      Term term = new Term(idField.getName(), indexedId);
//      num = ir.deleteDocuments(term);
//      if (core.log.isTraceEnabled()) {
//        core.log.trace( core.getLogId()+"deleted " + num + " docs matching id " + idFieldType.indexedToReadable(indexedId));
//      }
//    } finally {
//      try { if (tdocs != null) tdocs.close(); } catch (Exception e) {}
//    }
//    return num;
//  }
//
//  protected void overwrite(String indexedId, Document doc) throws IOException {
//    if (indexedId ==null) indexedId =getIndexedId(doc);
//    deleteInIndex(indexedId);
//    doAdd(doc);
//  }
//
//  /************** Direct update handler - pseudo code ***********
//  def add(doc, id, allowDups, overwritePending, overwriteCommitted):
//    if not overwritePending and not overwriteCommitted:
//      #special case... no need to check pending set, and we don't keep
//      #any state around about this addition
//      if allowDups:
//        committed[id]=doc  #100
//        return
//      else:
//        #if no dups allowed, we must check the *current* index (pending and committed)
//        if not committed[id]: committed[id]=doc  #000
//        return
//    #001  (searchd addConditionally)
//    if not allowDups and not overwritePending and pending[id]: return
//    del committed[id]  #delete from pending and committed  111 011
//    committed[id]=doc
//    pending[id]=True
//  ****************************************************************/
//
//  // could return the number of docs deleted, but is that always possible to know???
//  @Override
//  public void delete(DeleteUpdateCommand cmd) throws IOException {
//    if (!cmd.fromPending && !cmd.fromCommitted)
//      throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"meaningless command: " + cmd);
//    if (!cmd.fromPending || !cmd.fromCommitted)
//      throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"operation not supported" + cmd);
//    String indexedId = idFieldType.toInternal(cmd.id);
//    synchronized(this) {
//      deleteInIndex(indexedId);
//      pset.remove(indexedId);
//    }
//  }
//
//  // TODO - return number of docs deleted?
//  // Depending on implementation, we may not be able to immediately determine num...
//  @Override
//  public void deleteByQuery(DeleteUpdateCommand cmd) throws IOException {
//    if (!cmd.fromPending && !cmd.fromCommitted)
//      throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"meaningless command: " + cmd);
//    if (!cmd.fromPending || !cmd.fromCommitted)
//      throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"operation not supported: " + cmd);
//
//    Query q = QueryParsing.parseQuery(cmd.query, schema);
//
//    int totDeleted = 0;
//    synchronized(this) {
//      closeWriter(); openSearcher();
//
//      // if we want to count the number of docs that were deleted, then
//      // we need a new instance of the DeleteHitCollector
//      final DeleteHitCollector deleter = new DeleteHitCollector(searcher);
//      searcher.search(q, null, deleter);
//      totDeleted = deleter.deleted;
//    }
//
//    if (core.log.isDebugEnabled()) {
//      core.log.debug(core.getLogId()+"docs deleted:" + totDeleted);
//    }
//
//  }
//
//  /**************** old hit collector... new one is in base class
//  // final DeleteHitCollector deleter = new DeleteHitCollector();
//  class DeleteHitCollector extends HitCollector {
//    public int deleted=0;
//    public void collect(int doc, float score) {
//      try {
//        searcher.getReader().delete(doc);
//        deleted++;
//      } catch (IOException e) {
//        try { closeSearcher(); } catch (Exception ee) { SolrException.log(SolrCore.log,ee); }
//        SolrException.log(SolrCore.log,e);
//        throw new SolrException( SolrException.StatusCode.SERVER_ERROR,"Error deleting doc# "+doc,e);
//      }
//    }
//  }
//  ***************************/
//
//  @Override
//  public int mergeIndexes(MergeIndexesCommand cmd) throws IOException {
//    throw new SolrException(
//        SolrException.ErrorCode.BAD_REQUEST,
//        "DirectUpdateHandler doesn't support mergeIndexes. Use DirectUpdateHandler2 instead.");
//  }
//
//  @Override
//  public void commit(CommitUpdateCommand cmd) throws IOException {
//    Future[] waitSearcher = null;
//    if (cmd.waitSearcher) {
//      waitSearcher = new Future[1];
//    }
//
//    synchronized (this) {
//      pset.clear();
//      closeSearcher();  // flush any deletes
//      if (cmd.optimize || cmd.expungeDeletes) {
//        openWriter();  // writer needs to be open to optimize
//        if(cmd.optimize) writer.optimize(cmd.maxOptimizeSegments);
//        if(cmd.expungeDeletes) writer.expungeDeletes(cmd.expungeDeletes);
//      }
//      closeWriter();
//
//      callPostCommitCallbacks();
//      if (cmd.optimize) {
//        callPostOptimizeCallbacks();
//      }
//
//      core.getSearcher(UpdateHandler.UPDATEPARTION,true,true);
//    }
//
//    if (waitSearcher!=null && waitSearcher[0] != null) {
//      try {
//        waitSearcher[0].get();
//      } catch (InterruptedException e) {
//        SolrException.log(log,e);
//      } catch (ExecutionException e) {
//        SolrException.log(log,e);
//      }
//    }
//
//    return;
//  }
//
//  /**
//   * @since Solr 1.4
//   */
//  @Override
//  public void rollback(RollbackUpdateCommand cmd) throws IOException {
//    throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
//        "DirectUpdateHandler doesn't support rollback. Use DirectUpdateHandler2 instead.");
//  }
//
//
//  ///////////////////////////////////////////////////////////////////
//  /////////////////// helper method for each add type ///////////////
//  ///////////////////////////////////////////////////////////////////
//
//  protected int addNoOverwriteNoDups(AddUpdateCommand cmd) throws IOException {
//    if (cmd.indexedId ==null) {
//      cmd.indexedId =getIndexedId(cmd.doc);
//    }
//    synchronized (this) {
//      if (existsInIndex(cmd.indexedId)) return 0;
//      doAdd(cmd.doc);
//    }
//    return 1;
//  }
//
//  protected int addConditionally(AddUpdateCommand cmd) throws IOException {
//    if (cmd.indexedId ==null) {
//      cmd.indexedId =getIndexedId(cmd.doc);
//    }
//    synchronized(this) {
//      if (pset.contains(cmd.indexedId)) return 0;
//      // since case 001 is currently the only case to use pset, only add
//      // to it in that instance.
//      pset.add(cmd.indexedId);
//      overwrite(cmd.indexedId,cmd.doc);
//      return 1;
//    }
//  }
//
//
//  // overwrite both pending and committed
//  protected synchronized int overwriteBoth(AddUpdateCommand cmd) throws IOException {
//    overwrite(cmd.indexedId, cmd.doc);
//    return 1;
//  }
//
//
//  // add without checking
//  protected synchronized int allowDups(AddUpdateCommand cmd) throws IOException {
//    doAdd(cmd.doc);
//    return 1;
//  }
//
//
//  @Override
//  public int addDoc(AddUpdateCommand cmd) throws IOException {
//
//    // if there is no ID field, use allowDups
//    if( idField == null ) {
//      cmd.allowDups = true;
//      cmd.overwriteCommitted = false;
//      cmd.overwritePending = false;
//    }
//    
//    if (!cmd.allowDups && !cmd.overwritePending && !cmd.overwriteCommitted) {
//      return addNoOverwriteNoDups(cmd);
//    } else if (!cmd.allowDups && !cmd.overwritePending && cmd.overwriteCommitted) {
//      return addConditionally(cmd);
//    } else if (!cmd.allowDups && cmd.overwritePending && !cmd.overwriteCommitted) {
//      // return overwriteBoth(cmd);
//      throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"unsupported param combo:" + cmd);
//    } else if (!cmd.allowDups && cmd.overwritePending && cmd.overwriteCommitted) {
//      return overwriteBoth(cmd);
//    } else if (cmd.allowDups && !cmd.overwritePending && !cmd.overwriteCommitted) {
//      return allowDups(cmd);
//    } else if (cmd.allowDups && !cmd.overwritePending && cmd.overwriteCommitted) {
//      // return overwriteBoth(cmd);
//      throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"unsupported param combo:" + cmd);
//    } else if (cmd.allowDups && cmd.overwritePending && !cmd.overwriteCommitted) {
//      // return overwriteBoth(cmd);
//      throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"unsupported param combo:" + cmd);
//    } else if (cmd.allowDups && cmd.overwritePending && cmd.overwriteCommitted) {
//      return overwriteBoth(cmd);
//    }
//    throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"unsupported param combo:" + cmd);
//  }
//
//  @Override
//  public void close() throws IOException {
//    synchronized(this) {
//      closeSearcher();
//      closeWriter();
//    }
//  }
//
//
//
//  /////////////////////////////////////////////////////////////////////
//  // SolrInfoMBean stuff: Statistics and Module Info
//  /////////////////////////////////////////////////////////////////////
//
//  public String getName() {
//    return DirectUpdateHandler.class.getName();
//  }
//
//  public String getVersion() {
//    return SolrCore.version;
//  }
//
//  public String getDescription() {
//    return "Update handler that directly changes the on-disk main lucene index";
//  }
//
//  public Category getCategory() {
//    return Category.CORE;
//  }
//
//  public String getSourceId() {
//    return "$Id: DirectUpdateHandler.java 1065312 2011-01-30 16:08:25Z rmuir $";
//  }
//
//  public String getSource() {
//    return "$URL: https://svn.apache.org/repos/asf/lucene/dev/branches/lucene_solr_3_5/solr/core/src/java/org/apache/solr/update/DirectUpdateHandler.java $";
//  }
//
//  public URL[] getDocs() {
//    return null;
//  }
//
//  public NamedList getStatistics() {
//    NamedList lst = new SimpleOrderedMap();
//    return lst;
//  }
//



}
